from datetime import timedelta
from typing import Any
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPBearer
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from ...core.auth import (
    authenticate_user, 
    create_access_token,
    create_refresh_token,
    get_password_hash,
    verify_token,
    get_current_user
)
from ...core.config import settings
from ...database import get_db
from ...models.user import User, UserPreference
from ...services.forgot_password_service import ForgotPasswordService
from ...schemas.user import (
    UserRegister,
    UserLogin, 
    Token,
    TokenRefresh,
    TokenResponse,
    UserResponse,
    User as UserSchema,
    ForgotPasswordRequest
)
import logging

logger = logging.getLogger(__name__)
router = APIRouter()
security = HTTPBearer()


@router.post("/register", response_model=UserResponse)
async def register(
    user_data: UserRegister,
    db: AsyncSession = Depends(get_db)
) -> Any:
    try:
        # 检查用户名是否已存在
        stmt = select(User).where(
            (User.username == user_data.username) | 
            (User.email == user_data.email)
        )
        result = await db.execute(stmt)
        existing_user = result.scalar_one_or_none()
        
        if existing_user:
            if existing_user.username == user_data.username:
                raise HTTPException(
                    status_code=400,
                    detail="用户名已存在"
                )
            else:
                raise HTTPException(
                    status_code=400,
                    detail="邮箱已被注册"
                )
        
        # 创建新用户
        hashed_password = get_password_hash(user_data.password)
        db_user = User(
            username=user_data.username,
            email=user_data.email,
            password_hash=hashed_password,
            nickname=user_data.nickname or user_data.username,
            is_active=True,
            is_verified=False,
            login_count=0
        )
        
        db.add(db_user)
        await db.commit()
        await db.refresh(db_user)
        
        # 创建默认用户偏好
        user_preference = UserPreference(
            user_id=db_user.id,
            language='zh-CN',
            theme='light',
            voice_enabled=True,
            voice_speed='1.0',
            auto_play_voice=True,
            notification_enabled=True
        )
        
        db.add(user_preference)
        await db.commit()
        
        return UserResponse(
            code=200,
            message="注册成功",
            data=UserSchema.from_orm(db_user)
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"用户注册失败: {e}")
        await db.rollback()
        raise HTTPException(status_code=500, detail="注册失败，请稍后重试")


@router.post("/login", response_model=TokenResponse)
async def login(
    user_data: UserLogin,
    db: AsyncSession = Depends(get_db)
) -> Any:
    try:
        # 验证用户
        user = await authenticate_user(
            db, user_data.username, user_data.password
        )
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户名或密码错误",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        if not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户账户已被禁用"
            )
        
        # 更新登录信息
        user.login_count += 1
        await db.commit()
        
        # 创建访问令牌
        access_token_expires = timedelta(
            minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
        )
        access_token = create_access_token(
            data={"sub": str(user.id)}, 
            expires_delta=access_token_expires
        )
        
        # 创建刷新令牌
        refresh_token = create_refresh_token(data={"sub": str(user.id)})
        
        return TokenResponse(
            code=200,
            message="登录成功",
            data=Token(
                access_token=access_token,
                refresh_token=refresh_token,
                token_type="bearer",
                expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
            )
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"用户登录失败: {e}")
        raise HTTPException(status_code=500, detail="登录失败，请稍后重试")


@router.post("/refresh", response_model=TokenResponse)
async def refresh_token(
    token_data: TokenRefresh,
    db: AsyncSession = Depends(get_db)
) -> Any:
    try:
        # 验证刷新令牌
        payload = verify_token(token_data.refresh_token)
        if payload is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的刷新令牌",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        user_id: str = payload.get("sub")
        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的令牌数据",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        # 检查用户是否存在且激活
        stmt = select(User).where(User.id == int(user_id))
        result = await db.execute(stmt)
        user = result.scalar_one_or_none()
        if not user or not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户不存在或已被禁用",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        # 创建新的访问令牌
        access_token_expires = timedelta(
            minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
        )
        access_token = create_access_token(
            data={"sub": str(user.id)}, 
            expires_delta=access_token_expires
        )
        
        # 创建新的刷新令牌
        new_refresh_token = create_refresh_token(data={"sub": str(user.id)})
        
        return TokenResponse(
            code=200,
            message="令牌刷新成功",
            data=Token(
                access_token=access_token,
                refresh_token=new_refresh_token,
                token_type="bearer",
                expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
            )
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"令牌刷新失败: {e}")
        raise HTTPException(status_code=500, detail="令牌刷新失败")


@router.post("/logout")
async def logout(
    current_user: UserSchema = Depends(get_current_user)
) -> Any:
    return {
        "code": 200,
        "message": "登出成功",
        "data": None
    }


@router.get("/me", response_model=UserResponse)
async def get_current_user_info(
    current_user: UserSchema = Depends(get_current_user)
) -> Any:
    return UserResponse(
        code=200,
        message="获取用户信息成功",
        data=current_user
    )


@router.post("/forgot-password")
async def forgot_password(
    request: ForgotPasswordRequest,
    db: AsyncSession = Depends(get_db)
) -> Any:
    """
    忘记密码 - 通过邮箱和图形验证码重置密码
    """
    try:
        # 从请求头或session中获取图形验证码
        # 这里需要前端在请求时传递验证码
        # 实际实现中，验证码应该存储在session中
        session_captcha = request.captcha  # 临时方案，实际应该从session获取
        
        # 创建忘记密码服务实例
        forgot_password_service = ForgotPasswordService(db)
        
        # 重置密码
        success = await forgot_password_service.reset_password_by_email(
            email=request.email,
            captcha=request.captcha,
            new_password=request.new_password,
            session_captcha=session_captcha
        )
        
        if success:
            return {
                "code": 200,
                "message": "密码重置成功",
                "data": None
            }
        else:
            return {
                "code": 400,
                "message": "密码重置失败",
                "data": None
            }
            
    except Exception as e:
        logger.error(f"忘记密码API错误: {str(e)}")
        return {
            "code": 500,
            "message": str(e),
            "data": None
        } 